package com.dferreira.repository.services;

import java.util.ArrayList;

/**
 * Keeps the state of the package installation
 */
public class PackageInstallerState {


    private long totalBytesToInstall;
    private long totalBytesInstalled;
    private int numCurrentPkg;
    private int numCurrentFile;
    private boolean isRunning;
    private boolean isInstalling;
    private String pkgNameToInstall;
    private ArrayList<Integer> numFilesByPkg;
    private ArrayList<Integer> packagesIDs;

    /**
     * @param pkgNameToInstall    name from the package to install
     * @param totalBytesToInstall number of bytes to install
     */
    public PackageInstallerState(String pkgNameToInstall,
                                      long totalBytesToInstall) {
        this.pkgNameToInstall = pkgNameToInstall;
        this.totalBytesToInstall = totalBytesToInstall;
        this.totalBytesInstalled = 0;
        this.numCurrentPkg = -1;
        this.numCurrentFile = -1;
        this.isRunning = true;
        this.isInstalling = true;
        this.packagesIDs = new ArrayList<Integer>();
        this.numFilesByPkg = new ArrayList<Integer>();

    }


    /**
     * @return the total bytes to install
     */
    public long getTotalBytesToInstall() {
        return totalBytesToInstall;
    }


    /**
     * @return the total bytes already installed
     */
    public long getTotalBytesInstalled() {
        return totalBytesInstalled;
    }

    /**
     * @return the number of the current package
     */
    public int getNumCurrentPkg() {
        return numCurrentPkg;
    }

    /**
     * increase the number of current package
     */
    public void skipPkgNum() {
        this.numCurrentPkg++;
    }

    /**
     * Gets ready to receive another package
     *
     * @param pkgID identifier from the package to add to the list
     */
    public void addPkg(Integer pkgID) {
        this.numCurrentPkg++;
        this.packagesIDs.add(pkgID);
        this.numFilesByPkg.add(0);
        this.numCurrentFile = -1;
    }

    /**
     * Discards the information from  the last package
     */
    public synchronized void subPkg() {
        if (packagesIDs.size() != 0) {
            if (this.numFilesByPkg.size() != 0) {
                this.numFilesByPkg.remove(numFilesByPkg.size() - 1);
            }
            if (packagesIDs.size() != 0) {
                this.packagesIDs.remove(packagesIDs.size() - 1);
            }
            this.numCurrentPkg--;
        }
    }

    /**
     * @return identifier from the las package inserted
     */
    public Integer getLastPkgID() {
        if (packagesIDs.size() == 0)
            return null;
        return packagesIDs.get(packagesIDs.size() - 1);
    }

    /**
     * @return the number of the current file
     */
    public int getNumCurrentFile() {
        return numCurrentFile;
    }

    /**
     * @param bytesInstalled number of the byte that were installed because a file save
     */
    public synchronized void incFileNum(long bytesInstalled) {
        this.totalBytesInstalled += bytesInstalled;
        this.numCurrentFile++;
        this.numFilesByPkg.add(numFilesByPkg.size() - 1,
                this.numFilesByPkg.get(numFilesByPkg.size() - 1) + 1);
    }

    /**
     * @param bytesInstalled number of the byte that have been purged
     */
    public synchronized void decFileNum(long bytesInstalled) {
        if (numFilesByPkg.size() > 0) {
            this.numFilesByPkg.remove(numFilesByPkg.size() - 1);
            this.numCurrentFile--;
            this.totalBytesInstalled -= bytesInstalled;
        }
    }

    /**
     * @return if the task of installation is or not running
     */
    public boolean isRunning() {
        return isRunning;
    }

    /**
     * Set as not running
     */
    public void setNotRunning() {
        this.isRunning = false;
    }

    /**
     * @return the name from the package to install
     */
    public String getPkgNameToInstall() {
        return pkgNameToInstall;
    }


    /**
     * @return string tha represents the state from the installation package
     */
    @Override
    public String toString() {
        return "InstallExternalPackageState [installationFolder="
                + totalBytesToInstall + ", totalBytesInstalled="
                + totalBytesInstalled + ", numCurrentPkg=" + numCurrentPkg
                + ", numCurrentFile=" + numCurrentFile + ", isRunning="
                + isRunning + ", pkgNameToInstall=" + pkgNameToInstall + "]";
    }

    /**
     * @return if the package was or not installed
     */
    public boolean isInstalling() {
        return isInstalling;
    }

    /**
     * set the state as not installing
     */
    public void setAsNotInstalling() {
        this.isInstalling = false;
    }

}
